package com.sinosoft.platform.common.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

/**
 * @概述: 表单提交工具类
 */
@SuppressWarnings("deprecation")
public class HttpClientUtil {
	private static Logger logger = Logger.getLogger(HttpClientUtil.class);

	public static final String CHARSET_UTF_8 = "UTF-8";
	public static final String CHARSET_GBK = "GBK";
	public static final String CONTENT_TYPE_TEXT_HTML = "text/html";
	public static final String CONTENT_TYPE_APPLICATION_FORM = "application/x-www-form-urlencoded";
	private static HttpClient httpClient = null;
	private static final String HTTP_METHOD_GET = "GET";
	private static final String HTTP_METHOD_POST = "POST";
	private static final String CONTENT_TYPE = "text/html;charset=UTF-8";
	static {
		Protocol myhttps = new Protocol("https", new HttpsSecureProtocolSocketFactory(), 443);
		Protocol.registerProtocol("https", myhttps);
		httpClient = new HttpClient();
	}

	/**
	 * 提交数据
	 * 
	 * @return 是否提交成功
	 * @throws Exception
	 */
	public static String originalPostData(String urlStr, Map<String, String> paramMap) throws Exception {
		UTF8PostMethod procPost = new UTF8PostMethod(urlStr);
		System.out.println("%%%%%%%%%%%:  " + urlStr);
		Set<String> keySet = paramMap.keySet();

		for (Object key : keySet) {
			String keyValue = String.valueOf(key);
			String value = (String) paramMap.get(keyValue);
			if (value == null) {
				value = "";
			}
			procPost.addParameter(keyValue, value);
			System.out.println("parameter:" + keyValue + "=" + value);
		}

		httpClient.executeMethod(procPost);

		// 读取内容
		byte[] data = null;
		String result = null;
		try {
			data = procPost.getResponseBody();
			result = new String(data, "UTF-8");
//			result = procPost.getResponseBodyAsString();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;

	}
	
	/** 
	 * 发送报文到支付系统
	 * @Title: sendPaymentXml 
	 * @Description: TODO
	 * @param urlStr 请求地址
	 * @param paramMap 参数
	 * @param xml 报文
	 * @return
	 * @throws Exception
	*/ 
	public static String sendPaymentXml(Map<String, String> paramMap,String xml,String url) throws Exception {
		paramMap.put("dataXml", xml);
		return originalPostData(url,paramMap);
	}

	/**
	 * 提交数据
	 * 
	 * @return 是否提交成功
	 * @throws Exception
	 */
	public static String postData(String urlStr, Map<String, String> paramMap, String charsetType) throws Exception {

		UTF8PostMethod procPost = new UTF8PostMethod(urlStr);

		Set<String> keySet = paramMap.keySet();

		for (Object key : keySet) {
			String keyValue = String.valueOf(key);
			String value = (String) paramMap.get(keyValue);
			if (value == null) {
				value = "";
			}
			procPost.addParameter(keyValue, value);
		}

		httpClient.executeMethod(procPost);

		// 读取内容
		InputStream resInputStream = null;
		StringBuffer html = new StringBuffer();
		try {
			resInputStream = procPost.getResponseBodyAsStream();
			// 处理内容
			BufferedReader reader = new BufferedReader(new InputStreamReader(resInputStream, charsetType));
			String tempBf = null;
			while ((tempBf = reader.readLine()) != null) {

				html.append(tempBf);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (resInputStream != null) {
				resInputStream.close();
			}
		}
		return new String(html.toString().getBytes(charsetType), charsetType);
	}

	/**
	 * 提交数据With GBK
	 * 
	 * @return 是否提交成功
	 * @throws Exception
	 */
	public static String postData(String urlStr, Map<String, String> paramMap) throws Exception {
		return postData(urlStr, paramMap, "UTF-8");
	}

	// modify by wangxulu 2013-05-21 end

	public static String postJsonData(String urlStr, String xmlData) throws Exception {
		return postJsonData(urlStr, xmlData, "UTF-8");
	}

	public static String originalGetData(String urlStr) throws Exception {
		return originalGetData(urlStr, new HashMap<String, String>(), "UTF-8");
	}

	public static String originalGetData(String urlStr, Map<String, String> paramMap) throws Exception {
		return originalGetData(urlStr, paramMap, "UTF-8");
	}

	/**
	 * 提交数据
	 * 
	 * @return 是否提交成功
	 * @throws Exception
	 */
	public static String postJsonData(String urlStr, String xmlData, String charsetType) throws Exception {
		UTF8PostMethod post = new UTF8PostMethod(urlStr);
		post.setRequestBody(xmlData);
		httpClient.executeMethod(post);
		return getResponseXml(post.getResponseBodyAsStream());
	}

	public static String getResponseXml(InputStream is) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
		StringBuffer buffer = new StringBuffer();
		String demo = "";
		while ((demo = br.readLine()) != null) {
			buffer.append(demo);
		}
		String xml = buffer.toString();
		return xml;
	}

	/**
	 * 提交数据With GBK
	 * 
	 * @return 是否提交成功
	 * @throws Exception
	 */
	public static String postDataWithUTF8(String urlStr, Map<String, String> paramMap) throws Exception {
		return postData(urlStr, paramMap, "UTF-8");
	}

	/**
	 * 提交数据
	 * 
	 * @param urlStr
	 * @param paramMap
	 * @return
	 * @throws Exception
	 */
	public static String originalGetData(String urlStr, Map<String, String> paramMap, String charsetType) throws Exception {
		int i = 0;
		char c = 0;
		if (paramMap.size() > 0) {
			// param += "?";
			Set<String> keySet = paramMap.keySet();
			for (Object key : keySet) {
				i = urlStr.indexOf("?");
				if (i > 0) {
					c = '&';
				} else {
					c = '?';
				}

				String keyValue = String.valueOf(key);
				String value = (String) paramMap.get(keyValue);
				if (value == null) {
					value = "";
				} else {
					value =  URLEncoder.encode(value, charsetType);
				}
				urlStr += (c + keyValue + "=" + value);
			}
		}

		GetMethod procGet = new GetMethod(urlStr);
		httpClient.executeMethod(procGet);

		// 读取内容
		String result = null;
		try {
			result = procGet.getResponseBodyAsString();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;
	}

	public static String getDataUrl(String urlStr, Map<String, String> paramMap) throws Exception {
		int i = 0;
		char c = 0;
		if (paramMap.size() > 0) {
			Set<String> keySet = paramMap.keySet();
			for (Object key : keySet) {
				i = urlStr.indexOf("?");
				if (i > 0) {
					c = '&';
				} else {
					c = '?';
				}
				String keyValue = String.valueOf(key);
				String value = (String) paramMap.get(keyValue);
				if (value == null) {
					value = "";
				}
				urlStr += (c + keyValue + "=" + value);
			}
		}

		return urlStr;
	}

	/**
	 * @名称: 由UnionCode转为String
	 * @作者: Chen.yulong
	 * @创建于: 2011-8-29
	 * @param unicode
	 * @return
	 * @描述:
	 */
	public static String tozhCN(String unicode) {
		StringBuffer gbk = new StringBuffer();
		String[] hex = unicode.split("\\\\u");
		for (int i = 1; i < hex.length; i++) { // 注意要从 1 开始，而不是从0开始。第一个是空。
			int data = Integer.parseInt(hex[i], 16); // 将16进制数转换为 10进制的数据。
			gbk.append((char) data); // 强制转换为char类型就是我们的中文字符了。
		}
		// System.out.println("这是从 Unicode编码 转换为 中文字符了: " + gbk.toString());
		return gbk.toString();
	}

	/**
	 * 
	 * @名称: 由String转为UnionCode
	 * @作者: Chen.yulong
	 * @创建于: 2011-9-9
	 * @param zhStr
	 * @return
	 * @描述:
	 */
	public static String toUnicode(String zhStr) {
		StringBuffer unicode = new StringBuffer();
		for (int i = 0; i < zhStr.length(); i++) {
			char c = zhStr.charAt(i);
			unicode.append("\\u" + Integer.toHexString(c));
		}
		// System.out.println(unicode.toString());
		return unicode.toString();
	}

	private static void httpsProtocol() {
		Protocol myhttps = new Protocol("https", new HttpsSecureProtocolSocketFactory(), 443);
		Protocol.registerProtocol("https", myhttps);
	}
	
	public static String getRequest(String url, String queryString,
			String charSet, String contentType) {
		String encode = StringUtils.isNotEmpty(charSet) ? charSet
				: HttpClientUtil.CHARSET_UTF_8;
		String type = StringUtils.isNotEmpty(contentType) ? contentType
				: HttpClientUtil.CONTENT_TYPE_TEXT_HTML;

		String encodeUrl = url;
		logger.info("encodeUrl:"+encodeUrl);
		try {
			encodeUrl = URIUtil.encodeQuery(url, encode);
		} catch (URIException e) {
			e.printStackTrace();
		}
		logger.info("encodeUrl----------:"+encodeUrl);
		GetMethod get = new GetMethod(encodeUrl);
		get.addRequestHeader("Content-Type", type + ";charset=" + encode);

		if (StringUtils.isNotEmpty(queryString)) {
			get.setQueryString(queryString);
		}
		logger.info("url=" + url);
		return get(get, encode);
	}
	
	/**
	 * http get
	 * 
	 * @param charSet
	 *            default utf-8
	 * @return
	 */
	private static String get(GetMethod get, String charSet) {
		HttpClient httpClient = new HttpClient();
		int status = 0;
		InputStream is = null;

		try {
			status = httpClient.executeMethod(get);
			is = get.getResponseBodyAsStream();
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(e, e);
		}
		logger.info("status:"+status);
		return getResponse(status, is, charSet);
	}
	
	private static String getResponse(int status, InputStream is, String charSet) {
		String encode = StringUtils.isNotEmpty(charSet) ? charSet
				: HttpClientUtil.CHARSET_UTF_8;
		StringBuilder sb = new StringBuilder();
		if (status == 
			HttpStatus.SC_OK && is != null) {
			try {
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(is, encode));
				String line = null;
				while ((line = reader.readLine()) != null) {
					sb.append(line);
				}
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
				logger.error(e, e);
			} catch (IOException e) {
				e.printStackTrace();
				logger.error(e, e);
			} finally {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return sb.toString();
	}
	
	public static String getRequest(String url,String queryString){
        return request(url,HTTP_METHOD_GET,null, queryString);
    }
	
	private static String request(String url, String method,
			List<NameValuePair> list, String body) {
		StringBuilder sb = new StringBuilder();
		if (StringUtils.isEmpty(url)) {
			return "";
		}
		HttpClient httpClient = new HttpClient();

		int status = 0;
		InputStream is = null;
		if (method.equalsIgnoreCase("get")) {
			String encodeUrl = url;
			try {
				encodeUrl = URIUtil.encodeQuery(url, CHARSET_UTF_8);
			} catch (URIException e) {
				e.printStackTrace();
			}
			GetMethod get = new GetMethod(encodeUrl);
			get.addRequestHeader("Content-Type", CONTENT_TYPE);

			if (list != null && !list.isEmpty()) {
				NameValuePair[] arr = new NameValuePair[list.size()];
				get.setQueryString(list.toArray(arr));
			} else if (StringUtils.isNotEmpty(body)) {
				get.setQueryString(body);
			}
			try {
				logger.info("get = "+get);
				status = httpClient.executeMethod(get);
				is = get.getResponseBodyAsStream();
			} catch (IOException e) {
				e.printStackTrace();
				logger.error(e, e);
			}
		} else if (method.equalsIgnoreCase("post")) {
			PostMethod post = new PostMethod(url);
			post.addRequestHeader("Content-Type", CONTENT_TYPE);
			if (list != null && !list.isEmpty()) {
				NameValuePair[] arr = new NameValuePair[list.size()];
				post.setRequestBody(list.toArray(arr));
			} else if (StringUtils.isNotEmpty(body)) {
				post.setRequestBody(body);
			}
			try {
				status = httpClient.executeMethod(post);
				is = post.getResponseBodyAsStream();
			} catch (IOException e) {
				e.printStackTrace();
				logger.error(e, e);
			}
		}

		if (status == HttpStatus.SC_OK && is != null) {
			try {
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(is, CHARSET_UTF_8));
				String line = null;
				while ((line = reader.readLine()) != null) {
					sb.append(line);
				}
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
				logger.error(e, e);
			} catch (IOException e) {
				e.printStackTrace();
				logger.error(e, e);
			} finally {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return sb.toString();
	}
}

/**
 * 重写PostMethod以解决UTF-8编码问题
 * 
 * @author adun
 */
class UTF8PostMethod extends PostMethod {
	public UTF8PostMethod(String url) {
		super(url);
	}

	@Override
	public String getRequestCharSet() {
		return "UTF-8";
	}
}
